#include <stdlib.h>
#include <sys/time.h>
#include <stdio.h>
#include "../common/rz_random.h"

#define V if(verbose) printf

int verbose = 1;

int round(double a) {
    int r=(int) a;
    double t=a-r;
    if (t>0.5) return r+1;
    return r;
}

inline double mlap(struct timeval start) {
    struct timeval end;
    gettimeofday(&end, NULL);
//    return (end.tv_sec-start.tv_sec)*1000+(end.tv_usec-start.tv_usec)/1000;
    return (end.tv_sec-start.tv_sec)+(end.tv_usec-start.tv_usec)/1000000.0;
}


int mul_sqr_mat(double* a, double* b, double* c, int n) {
//  c=a*b
//  all matrixes are n by n , and all are pre allocated (including c)
    int i,j,k;
    for (i=0;i<n;i++) {
	for(j=0;j<n;j++) {
	    *(c+i*n+j)=0.0;
	    for (k=0;k<n;k++) {
		*(c+i*n+j)+=(*(a+i*n+k) * *(b+k*n+j));
	    }
	}
    }
	    
}

int main() {
    int N=1000;
    unsigned long long ops,tt;
    ops=N*N*sizeof(double);
    double* a= (double*) malloc(ops);
    double* b= (double*) malloc(ops);
    double* c= (double*) malloc(ops);
    struct timeval start;
    double t,flops,mflops;
    int i,j;
    unsigned long index;

    V("Benchmarking with multiplying two %d by %d matrixes.\n",N,N);
    V("Generating matrixes ... "); 
    for (i=0;i<N;i++) {
	for(j=0;j<N;j++) {
	    index=i*N+j;
	    *(a+index)=prand()*1000;
	    *(b+index)=prand()*1000;
	}
    }
    V("done!\n");

    V("Multiplying ... ");
    gettimeofday(&start, NULL);
    mul_sqr_mat(a,b,c,N);
    t=mlap(start);
    V("done!\n");
    
    ops=N*N;
    ops*=N*2;
    tt=ops/1000000;
    mflops=tt/t;
    printf("real time = %.6f\n",t);
    printf("mflops = %.6f\n",mflops);
    printf("rank = %d\n",round(mflops/10));
    

    return 0;
}
